using System;
using System.Collections.Generic;
using IBS.Bll.Cards;
using IBS.ServiceContracts;
using IBS.Bll.Accounts;
using IBS.Model;
using IBS.Bll.Tools;
using IBS.Model.Base;
using IBS.Bll;
using log4net;
using System.Linq;
namespace IBS.Bll.Payments
{
    // Workflow:
    // 1. RequestAdditionalInformation (client + payment type + contract id)  - to display the data on UI
    // 2. ProcessPayment

    public class PaymentService : ServiceBase, IPaymentService
    {
        private readonly ISecurityService _securityService;
        private readonly IAccountService _accountService;
        private readonly ICardService _cardService;
        private readonly ITransferService _transferService;
        private IKnowledgeBaseService _knowledgeBaseService;

        public PaymentService(IIbsContext context,
            ISecurityService securityService,
            IAccountService accountService,
            ICardService cardService,
            ITransferService transferService,
            IKnowledgeBaseService knowledgeBaseService)
            : base(context)
        {
            _securityService = securityService;
            _accountService = accountService;
            _cardService = cardService;
            _transferService = transferService;
            _knowledgeBaseService = knowledgeBaseService;
        }

        public string GetBillingInformation(Client client, Payment payment)
        {
            var result = FillBillingInformation(payment.PaymentDetailTemplate);
            return result;
        }

        private string FillBillingInformation(string xml)
        {
            return xml;
        }

        public Transfer PayPayment(string fromCardNumber, int paymentId, string paymentDetail, decimal amount, string ISO, string useName)
        {
            var fromCard = _cardService.GetCardByNumber(fromCardNumber);
            var payment = GetPaymentById(paymentId);

            if (!_securityService.IsCardOwner(fromCard, useName))
                throw new BusinessException("You can't do this operation");

            if (fromCard.IsBlocked || fromCard.Account.IsBlocked)
                throw new BusinessException("Your card or account is blocked. Unlock it and try again");

            if (payment.Account.IsBlocked)
                throw new BusinessException("Payment is blocking now");

            return _transferService.PayPayment(fromCard, payment, paymentDetail, amount, ISO, useName);
        }

        public IList<Payment> GetPayments(Func<Payment, bool> criteria = null, int? page = null)
        {
            var result = _context.Payments
                .GetByCriteria(page, criteria);
            return result;
        }

        public IList<Payment> GetEripPayments(Func<Payment, bool> criteria = null, int? page = null)
        {
            var eripAccount = _accountService.EripAccount;
            var result = _context.Payments
                .GetByCriteria(page, criteria)
                .Where(p => p.Account.Id == eripAccount.Id);
            return result.ToList();
        }

        public IList<Payment> GetNotEripPayments(Func<Payment, bool> criteria, int? page = null)
        {
            var eripAccount = _accountService.EripAccount;
            var result = _context.Payments
                .GetByCriteria(page, criteria)
                .Where(p => p.Account.Id != eripAccount.Id);
            return result.ToList();
        }

        public Payment GetPaymentById(int paymentId)
        {
            try
            {
                return _context.Payments.Single(p => p.Id == paymentId);
            }
            catch (InvalidOperationException)
            {

                throw new BusinessException("Payment does not exist");
            }
        }

        public void CreateEripPayment(string paymentDetail, int? clientId = null)
        {
            var eripClient = _knowledgeBaseService.GetClients(c => c.Id == 2).Single();
            var eripAccount = _accountService.EripAccount;
            var payment = new Payment()
            {
                AccountId = eripAccount.Id,
                OwnerId = eripClient.Id,
                PaymentDetailTemplate = paymentDetail,
            };
            _context.Payments.AddObject(payment);
            _context.SaveChanges();
        }

        public void CreatePayment(string paymentDetail, int? clientId = null)
        {
            clientId = clientId ?? 1;
            var client = _knowledgeBaseService.GetClientById(clientId.Value);
            var paymentAccount = _accountService.CreateAccount(client, "BYR", "script");
            var payment = new Payment()
            {
                AccountId = paymentAccount.Id,
                OwnerId = client.Id,
                PaymentDetailTemplate = paymentDetail,
            };
            _context.Payments.AddObject(payment);
            _context.SaveChanges();
        }
    }
}

